#include<iostream>
#include<unistd.h>//(pipe)(sleep)
#include<cassert>//(assert)
#include<sys/types.h>//(waitpid)
#include<sys/wait.h>//(waitpid)
#include<cstring>//(strlen)
using namespace std;
int main()
{
    //第一步：创建管道文件，打开读写端
    int fds[2];
    int n = pipe(fds);
    assert(n == 0);

    //第二部：创建进程，fork()
    //fork() 在父进程中返回子进程的 PID。
    //在子进程中返回 0。

    pid_t id = fork();//pid_t 是一个有符号整数类型，通常是 int 或 long 的别名。fork返回-1表示失败
    assert(id >= 0);
    if(id == 0)
    {
        //子进程
        //子进程进行写入
        close(fds[0]);//关闭文件读的功能，只保留写的功能
        //子进程的通讯代码
        const char* s = "我是子进程，我正在和你发消息";
        int cnt = 0;
        while (true)
        {
            cnt++;
            char buffer[1024];
            snprintf(buffer,sizeof buffer,"child->parent say:%s[%d]【%d】",s,cnt, getpid());
            write(fds[1],buffer,strlen(buffer));//系统函数，以二进制的方式写入，不需要考虑/0
            sleep(1);
        }
        
        exit(0);//正常退出
    }
    //父进程
    //父进程进行读取
    close(fds[1]);//关闭文件写的功能，只保留读的功能
    //父进程的通讯代码
    while(true)
    {
        char buffer[1024];
        ssize_t s = read(fds[0],buffer,sizeof(buffer) - 1);//返回实际读取的字节数
        if(s > 0 ) buffer[s] = 0;//将最后一个/0，方便打印
        cout<<"Get Message#" <<buffer <<"| my pid "<< getpid()<< endl;
    }
    n = waitpid(id, nullptr , 0);//如果传入 nullptr，表示父进程不关心子进程的退出状态---0 表示默认行为，即阻塞等待，直到目标子进程结束
    assert(n == id);//成功时返回结束的子进程的 PID,

    return 0;
}